#include <iostream>
#include <mutex>
using namespace std;

// 设置一个类不可被拷贝
// 不可被拷贝，将其拷贝构造以及赋值重载取消掉即可。
//class NoCopy
//{
//public:
//	NoCopy() {}
//private:
//	NoCopy(const NoCopy&){}
//	NoCopy& operator=(const NoCopy&);
//};

//class NoCopy
//{
//public:
//	NoCopy()
//	{
//		cout << "构造函数" << endl;
//	}
//	NoCopy(const NoCopy&) = delete;
//	//NoCopy(NoCopy&&) = delete;
//
//	//NoCopy& operator=(const NoCopy&) = default;
//	//NoCopy& operator=(NoCopy&&) = delete;
//};

// 设计一个类，只能在堆上创建
//class NoStack
//{
//public:
//	static NoStack* create_NoStack()
//	{
//		return new NoStack;
//	}
//private:
//	NoStack() {}
//	NoStack(const NoStack&) {}
//};

//class NoStack
//{
//public:
//	void Delete()
//	{
//		delete this;
//	}
//private:
//	~NoStack() = default;
//};

// 设计一个类，只能在栈上创建
//class NoHeap
//{
//public:
//	static NoHeap crate_NoHeap()
//	{
//		return NoHeap();
//	}
//private:
//	NoHeap() = default;
//};

// 单例模式
// 饿汉模式 开局就初始化对象，不存在线程安全问题
class HungryModel
{
public:
	static HungryModel* getObj()
	{
		return _obj;
	}
private:
	// 构造函数私有化，禁止拷贝
	HungryModel() {}
	HungryModel(const HungryModel&) = delete;
	HungryModel& operator=(const HungryModel&) = delete;

	static HungryModel* _obj;
};
HungryModel* HungryModel::_obj = new HungryModel;

// 懒汉模式 多执行流同时执行，存在线程安全问题
class LazyModel
{
public:
	//static LazyModel* getrObj()
	//{
	//	if (_obj == nullptr)
	//	{
	//		_mtx->lock();
	//		if (_obj == nullptr)
	//		{
	//			_obj = new LazyModel;
	//		}
	//		_mtx->unlock();
	//	}
	//	return _obj;
	//}

	static LazyModel* getrObj()
	{
		if (_obj == nullptr)
		{
			unique_lock<mutex> lock(*_mtx);  // 锁的智能指针进行管理退出作用域的时候自动释放锁 - 局部变量
			if (_obj == nullptr)
			{
				_obj = new LazyModel;
			}
		}
		return _obj;
	}
private:
	LazyModel() {};
	LazyModel(const LazyModel&) = delete;
	LazyModel& operator=(const LazyModel&) = delete;

	static LazyModel* _obj;
	static mutex* _mtx;
};
LazyModel* LazyModel::_obj = nullptr;
mutex* LazyModel::_mtx = new mutex;

void test_1()
{
	//NoCopy n1, n2;
	//NoCopy n3(n1);
	//n2 = n1;
	//NoCopy n4(move(n1));
	//n1 = NoCopy();

	//NoStack s1;
	//NoStack* s2 = NoStack::create_NoStack();
	//delete s2;

	//NoStack s1;
	//NoStack* s2 = new NoStack;
	//delete s2;
	//s2->Delete();

	LazyModel* obj = LazyModel::getrObj();

}

int main()
{
	test_1();  // 2023/5/29
	return 0;
}